/*
 * @Author: Troubadour 2276791354@qq.com
 * @Date: 2025-04-13 00:11:01
 * @LastEditors: Troubadour 2276791354@qq.com
 * @LastEditTime: 2025-04-13 14:24:43
 * @Version:
 * @Description:
 */

/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Include file                                                                       -
--------------------------------------------------------------------------------------------------------------------------------------*/
#include "SoftwareUart.h"
#include <stdio.h>
#include "main.h"
#include "tim.h"

/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Internal macro                                                                     -
--------------------------------------------------------------------------------------------------------------------------------------*/
// 系统时钟，单位：1Hz
#define SOFTWARE_SYS_CLOCK      84000000 // 84MHz

#define SOFTWARE_TX_PIN_SET()   HAL_GPIO_WritePin(SoftUart_TX_GPIO_Port, SoftUart_TX_Pin, GPIO_PIN_SET)     // 设置 TX 引脚为高电平
#define SOFTWARE_TX_PIN_RESET() HAL_GPIO_WritePin(SoftUart_TX_GPIO_Port, SoftUart_TX_Pin, GPIO_PIN_RESET)   // 设置 TX 引脚为低电平

/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Internal variables                                                                 -
--------------------------------------------------------------------------------------------------------------------------------------*/
static uint32_t BaudRateDelayTick = 0; // 默认波特率
static bool uartInitialized = false;

/*-------------------------------------------------------------------------------------------------------------------------------------
-                                                  Internal function                                                                  -
--------------------------------------------------------------------------------------------------------------------------------------*/

static void SoftwareUart_delayTick(uint32_t Tick)
{
#if 0
    /* Configure this function to use the timer you want */
    uint16_t tim_cnt = (uint16_t)Tick; // 计算定时器计数值

    // HAL_TIM_Base_Stop(&htim11); // 停止定时器
    __HAL_TIM_SET_COUNTER(&htim11, 0); // 重置计数器
    // HAL_TIM_Base_Start(&htim11); // 启动定时器
    while (__HAL_TIM_GET_COUNTER(&htim11) < tim_cnt); // 等待定时器计数到达指定值
    // HAL_TIM_Base_Stop(&htim11); // 停止定时器
#else
    /*
        1. NOP 指令：1 个时钟周期。
        2. 减法操作 (Tick--)：1 个时钟周期。
        3. 条件判断 (while)：1~2 个时钟周期。
    */
    Tick /= 4;
    while (Tick--)
    {
        __asm volatile("NOP"); // 空操作，等待一个时钟周期
    }
#endif
}

/**
 * @brief 初始化模拟串口
 * @param baudRate 波特率，单位：bps
 * @return true 初始化成功，false 初始化失败
 */
bool SoftwareUart_Init(uint32_t baudRate)
{
    switch (baudRate)
    {
        case 9600:
        case 19200:
        case 38400:
        case 57600:
        case 76800:
        case 115200:
        case 230400:
        case 256000:
        case 460800:
        case 921600:
            BaudRateDelayTick = (uint32_t)((SOFTWARE_SYS_CLOCK + baudRate / 2) / baudRate); // 计算波特率延迟时间
            break;
        default:
            return false; // 不支持的波特率
    }

    uartInitialized = true; // 设置初始化标志
    SOFTWARE_TX_PIN_SET();  // 设置 TX 引脚为高电平
    return true;
}

/**
 * @brief 发送一个字节的数据
 * @param data 要发送的数据
 */
void SoftwareUart_SendByte(uint8_t data)
{
    if (!uartInitialized)
    {
        return; // 未初始化
    }

    // __set_PRIMASK(1); // 禁用中断，防止中断干扰发送过程

    // 模拟起始位（低电平）
    SOFTWARE_TX_PIN_RESET(); // 设置 TX 引脚为低电平
    SoftwareUart_delayTick(BaudRateDelayTick); // 等待一个位时间

    // 发送数据位（8位）
    for (uint8_t i = 0; i < 8; i++)
    {
        if (data & (1 << i)) // 发送数据的每一位
        {
            SOFTWARE_TX_PIN_SET(); // 设置 TX 引脚为高电平
        }
        else
        {
            SOFTWARE_TX_PIN_RESET(); // 设置 TX 引脚为低电平
        }
        // 减去程序执行的tick数
        SoftwareUart_delayTick(BaudRateDelayTick); // 等待一个位时间
    }

    // 模拟停止位（高电平）
    SOFTWARE_TX_PIN_SET(); // 设置 TX 引脚为高电平
    SoftwareUart_delayTick(BaudRateDelayTick); // 等待一个位时间

    // __set_PRIMASK(0); // 启用中断，恢复中断状态
}

int fputc(int ch, FILE *f)
{
    SoftwareUart_SendByte((uint8_t)ch); // 发送字符
    return ch; // 返回发送的字符
}


